package com.rich.widget.span

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Paint.FontMetricsInt
import android.text.style.ReplacementSpan
import androidx.annotation.IntRange

/**
 *  基础类
 */
abstract class FontSpan : ReplacementSpan() {

    /** 测量的文本宽度  */
    var measureTextWidth = 0F
        private set

    /**
     *@param paint 画笔
     * @param text  当前文字
     * @param start 字符起始位置索引
     * @param end   字符终止位置索引
     * @param fm    字体测量属性
     * @return 返回值就是Span替换文字后所占的宽度
     */
    override fun getSize(
        paint: Paint,
        text: CharSequence,
        start: Int,
        end: Int,
        fm: FontMetricsInt?
    ): Int {
        measureTextWidth = onMeasure(paint, text, start, end, fm)

        // 这段不可以去掉，字体高度没设置，会出现 draw 方法没有被调用的问题
        // 详情请见：https://stackoverflow.com/questions/20069537/replacementspans-draw-method-isnt-called
        fm?.let {
            val metrics = paint.fontMetricsInt
            fm.top = metrics.top
            fm.ascent = metrics.ascent
            fm.descent = metrics.descent
            fm.bottom = metrics.bottom
        }
        return measureTextWidth.toInt()
    }

    /**
     * 将span回执到画布上.
     * @param canvas 画布
     * @param text 当前文字
     * @param start 字符起始位置索引
     * @param end 字符终止位置索引
     * @param x
     * @param top 该行文字显示区域的top值
     * @param y 字体的baseline值
     * @param bottom 该行文字显示区域的bottom值
     * @param paint 画笔
     */
    override fun draw(
        canvas: Canvas,
        text: CharSequence,
        start: Int,
        end: Int,
        x: Float,
        top: Int,
        y: Int,
        bottom: Int,
        paint: Paint
    ) {
        val alpha = paint.alpha
        // 判断是否给画笔设置了透明度
        if (paint.alpha != 255) {
            // 如果是则设置不透明
            paint.alpha = 255
        }
        onDraw(canvas, paint, text, start, end, x, top, y, bottom)
        // 绘制完成之后将画笔的透明度还原回去
        paint.alpha = alpha
    }

    /**
     *  测量文字宽度可重载.
     */
    open fun onMeasure(
        paint: Paint,
        text: CharSequence?,
        @IntRange(from = 0) start: Int,
        @IntRange(from = 0) end: Int,
        fontMetricsInt: FontMetricsInt?
    ): Float = paint.measureText(text, start, end)

    /**
     * 抽象函数绘制
     */
    abstract fun onDraw(
        canvas: Canvas,
        paint: Paint,
        text: CharSequence,
        @IntRange(from = 0) start: Int,
        @IntRange(from = 0) end: Int,
        x: Float,
        top: Int,
        y: Int,
        bottom: Int
    )
}